home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / inetray / lbuffer.c < prev    next >
C/C++ Source or Header  |  1993-08-15  |  4KB  |  193 lines

  1. /*======================================================================
  2.                     L B U F F E R . C 
  3.                     doc: Mon Apr 26 16:11:25 1993
  4.                     dlm: Mon May 17 10:01:05 1993
  5.                     (c) 1993 ant@notylia
  6.                     uE-Info: 66 6 T 0 0 72 2 2 8 ofnI
  7. ======================================================================*/
  8.  
  9. #include    <stdio.h>
  10. #include    <signal.h>
  11. #include    <sys/types.h>
  12. #include    <sys/time.h>
  13.  
  14. /*#define DEBUG                        /* show ops */
  15. /*#define    MLIMIT    100                /* memory limit */
  16.  
  17. #define    LBSIZE    (1024-sizeof(struct lBlock *)-sizeof(int)) /* block size */
  18. #define LBALLOC() (lBlock *)malloc(sizeof(lBlock))    /* alloc block */
  19. #define    FOREVER    while(1)
  20.  
  21. #define    IN    0
  22. #define    OUT    1
  23.  
  24. typedef struct lBlock {                    /* live block */
  25.     struct lBlock *next;
  26.     int    used;
  27.     char    buf[LBSIZE];
  28. } lBlock;
  29.  
  30. static lBlock *head;
  31.  
  32. static void fill(in,statusP)                /* fill buffer */
  33. int in,statusP;
  34. {
  35.     lBlock     *tail;
  36.     int    nRead,remain,nBlocks=0,maxFd;
  37.     fd_set    selRead;
  38.     
  39.     head = tail = LBALLOC();            /* alloc 1st */
  40.     if (head == NULL) {
  41.         fprintf(stderr,"lBuffer malloc() failed\n");
  42.         exit(1);
  43.     } else nBlocks++;
  44.     head->used = 0;
  45.     head->next = NULL;
  46.     remain = LBSIZE;
  47.  
  48. #ifdef DEBUG
  49.     fprintf(stderr,"Filling lBuffer...\n");
  50. #endif
  51.     do {                        /* build buffer */
  52.         FD_ZERO(&selRead);            /* detect death */
  53.         FD_SET(in,&selRead); maxFd = in;
  54.         if (statusP >= 0)
  55.             FD_SET(statusP,&selRead);
  56.         if (statusP > maxFd)
  57.             maxFd = statusP;
  58.         if (select(maxFd+1,&selRead,NULL,NULL,NULL) < 0) {
  59.             perror("lBuffer select");
  60.             exit(1);
  61.         }
  62.         if ((statusP >= 0) &&            /* father dead */
  63.             FD_ISSET(statusP,&selRead)) {
  64. #ifdef DEBUG
  65.                 fprintf(stderr,"Exiting due to parent death...\n");
  66. #endif
  67.             exit(1);
  68.         }
  69.  
  70.         nRead = read(in,&tail->buf[tail->used],    /* read block */
  71.                     remain);
  72.         if (nRead < 0) {
  73.             perror("lBuffer read");
  74.             exit(1);
  75.         }
  76.         tail->used += nRead;
  77.         remain -= nRead;
  78.  
  79.         if (nRead == 0) break;            /* eof */
  80.         if (tail->buf[tail->used-1] == '\0') {
  81.             tail->used--;
  82.             break;
  83.         }
  84.  
  85.         if (remain == 0) {            /* next block */
  86.             tail->next = LBALLOC();
  87.             if (tail->next == NULL) {
  88.                 fprintf(stderr,"lBuffer malloc() failed\n");
  89.                 exit(1);
  90.             } else {
  91.                 nBlocks++;
  92. #ifdef MLIMIT
  93.                 if (nBlocks > MLIMIT) {
  94.                     fprintf(stderr,"lBuffer MLIMIT\n");
  95.                     exit(1);
  96.                 }
  97. #endif
  98.                         }
  99.             tail = tail->next;
  100.             tail->used = 0;
  101.             tail->next = NULL;
  102.             remain = LBSIZE;
  103.         }
  104.     } FOREVER;
  105.     close(in);
  106. }
  107.  
  108. static void drain(out)                    /* drain buffer */
  109. int out;
  110. {
  111.     lBlock *cur;
  112.  
  113.     cur = head;
  114. #ifdef DEBUG
  115.     fprintf(stderr,"Draining lBuffer...\n");
  116. #endif
  117.     do {
  118.         if (write(out,cur->buf,cur->used) != cur->used) {
  119.             perror("lBuffer write");
  120.             exit(1);
  121.         }
  122.         cur = cur->next;
  123.     } while (cur != NULL);
  124.     close(out);
  125. }
  126.     
  127. /*======================================================================*/
  128.  
  129. static killed()                        /* killed nicely */
  130. {
  131.     exit(0);
  132. }
  133.  
  134. lPreBuffer(out1,out2)                    /* buf twice */
  135. int out1[2],out2[2];
  136. {
  137.     int pid,statusP[2];
  138.  
  139.     if (pipe(statusP) < 0) {            /* status pipe */
  140.         perror("lBuffer pipe");
  141.         exit(1);
  142.     }
  143.     if ((pid = fork()) < 0) {            /* build proc */
  144.         perror("lBuffer fork");
  145.         exit(1);
  146.     }
  147.     if (pid > 0) {                    /* father continues */
  148.         close(statusP[IN]);
  149.         close(out1[OUT]);
  150.         close(out2[OUT]);
  151.         return pid;
  152.     }
  153.  
  154.     signal(SIGALRM,SIG_IGN);            /* child buffers */
  155.     signal(SIGINT,SIG_IGN);                /* enable killing */
  156.     signal(SIGUSR1,killed);
  157.     close(statusP[OUT]);
  158.     close(out1[IN]);    
  159.     close(out2[IN]);
  160.     fill(IN,statusP[IN]);
  161.     signal(SIGUSR1,SIG_IGN);            /* disable killing */
  162.     drain(out1[OUT]);
  163.     drain(out2[OUT]);
  164.     exit(0);
  165. }
  166.  
  167. lPostBuffer(in,out)                    /* buf once */
  168. int in,out[2];
  169. {
  170.     int pid;
  171.  
  172. #ifdef DEBUG
  173.     fprintf(stderr,"lPostBuffer()\n");
  174. #endif
  175.     if ((pid = fork()) < 0) {            /* build proc */
  176.         perror("lBuffer fork");
  177.         exit(1);
  178.     }
  179.     if (pid > 0) {                    /* father continues */
  180.         close(out[OUT]);
  181.         return pid;
  182.     }
  183.  
  184.     signal(SIGALRM,SIG_IGN);            /* child buffers */
  185.     close(out[IN]);
  186.     fill(in,-1);
  187.     drain(out[OUT]);
  188. #ifdef DEBUG
  189.     fprintf(stderr,"lPostBuffer normal exit\n");
  190. #endif
  191.     exit(0);
  192. }
  193.